package cn.elwy.rcp.ui.wizard;

import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

import cn.elwy.common.util.AssertUtil;
import cn.elwy.rcp.core.model.ui.DialogInfo;
import cn.elwy.rcp.core.model.ui.DialogType;
import cn.elwy.rcp.ui.composite.WizardAreaComposite;
import cn.elwy.rcp.ui.config.DialogConfigFactory;
import cn.elwy.rcp.ui.config.DialogConfigListener;
import cn.elwy.rcp.ui.dialog.CDialog;
import cn.elwy.rcp.ui.listener.CloseListenerAdapter;

/**
 * 所有自定义对话框的父类
 * @author huangsq
 * @version 1.0, 2013-11-20
 * @since 1.0, 2013-11-20
 */
public class CWizardDialog extends CDialog {

  private static final String BASE_DIALOG = "CWizardDialog";

  private boolean isDirty;
  private Job job;

  private String dialogId = BASE_DIALOG;
  private DialogInfo dialogInfo;
  private BaseWizard wizard;
  private CloseDialogAdapter closeDialogAdapter;

  private WizardAreaComposite wizardAreaComposite;

  public CWizardDialog(Shell shell, BaseWizard wizard) {
    this(shell, wizard, wizard.getDialogId());
  }

  /**
   * @wbp.parser.constructor
   */
  public CWizardDialog(Shell shell, BaseWizard wizard, String dialogId) {
    super(shell);
    setWizard(wizard);
    setDialogId(dialogId);
  }

  @Override
  public int open() {
    init();
    int open = super.open();
    save();
    return open;
  }

  protected void init() {
    Wizard wizard = (Wizard) getWizard();
    if (AssertUtil.isNotEmpty(getHelpContextId())) {
      wizard.setHelpAvailable(true);
      PlatformUI.getWorkbench().getHelpSystem().setHelp(getShell(), getHelpContextId());
    }
    DialogInfo dialogInfo = getDialogInfo();

    create();
    getShell().setSize(dialogInfo.getWidth(), dialogInfo.getHeight());
    getShell().setLocation(getLocation());
    getShell().setMinimumSize(dialogInfo.getMinimumWidth(), dialogInfo.getMinimumHeight());
    getShell().setMaximized(dialogInfo.isMaximized());

    DialogConfigListener dialogConfigListener = new DialogConfigListener();
    dialogConfigListener.setDialogInfo(dialogInfo);
    getShell().addControlListener(dialogConfigListener);
  }

  protected void save() {
    if (getDialogInfo().isCanSave()) {
      DialogConfigFactory.saveDialogInfo(dialogInfo);
    }
  }

  @Override
  protected Control createContents(Composite parent) {
    DialogConfigListener dialogConfigListener = new DialogConfigListener();
    dialogConfigListener.setDialogInfo(dialogInfo);
    getShell().addControlListener(dialogConfigListener);
    getShell().setSize(dialogInfo.getWidth(), dialogInfo.getHeight());
    getShell().setLocation(getLocation());
    getShell().setMinimumSize(dialogInfo.getMinimumWidth(), dialogInfo.getMinimumHeight());
    getShell().setMaximized(dialogInfo.isMaximized());

    Composite composite = new Composite(parent, 0);
    GridLayout layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    layout.verticalSpacing = 0;
    composite.setLayout(layout);
    composite.setLayoutData(new GridData(GridData.FILL_BOTH));
    applyDialogFont(composite);
    // initialize the dialog units
    initializeDialogUnits(composite);

    createWizard(composite);

    return composite;
  }

  protected void createWizard(Composite parent) {
    wizardAreaComposite = new WizardAreaComposite(parent, wizard);
    wizardAreaComposite.setLayoutData(new GridData(GridData.FILL_BOTH));

    wizardAreaComposite.setCreateHeade(true);
    closeDialogAdapter = new CloseDialogAdapter();
    wizardAreaComposite.setCloseListenerAdapter(closeDialogAdapter);
    wizardAreaComposite.createContents();
  }

  /** 设置窗口居中 */
  protected Point getLocation() {
    if (!getDialogInfo().isCenter()) {
      return new Point(dialogInfo.getX(), dialogInfo.getY());
    }
    Rectangle shellBounds = null;
    if (getParentShell() == null) {
      shellBounds = Display.getCurrent().getBounds();
    } else {
      shellBounds = getParentShell().getBounds();
    }
    Point dialogSize = getShell().getSize();
    return new Point(shellBounds.x + (shellBounds.width - dialogSize.x) / 2,
        shellBounds.y + (shellBounds.height - dialogSize.y) / 2);
  }

  @Override
  protected int getShellStyle() {
    return super.getShellStyle() | getDialogInfo().getStyle();
  }

  /** 设置窗口居中 */
  @Override
  protected Point getInitialLocation(Point initialSize) {
    if (!dialogInfo.isCenter()) {
      return new Point(dialogInfo.getX(), dialogInfo.getY());
    }
    Rectangle shellBounds = null;
    if (getParentShell() == null) {
      shellBounds = Display.getCurrent().getBounds();
    } else {
      shellBounds = getParentShell().getBounds();
    }
    Point dialogSize = initialSize;
    return new Point(shellBounds.x + (shellBounds.width - dialogSize.x) / 2,
        shellBounds.y + (shellBounds.height - dialogSize.y) / 2);
  }

  @Override
  protected void configureShell(Shell newShell) {
    super.configureShell(newShell);
  }

  @Override
  protected void setShellStyle(int newShellStyle) {
    super.setShellStyle(newShellStyle);// | SWT.DIALOG_TRIM);// | SWT.APPLICATION_MODAL);
    // SWT.BORDER //建立一个有边框但没有标题栏的窗口
    // SWT.CLOSE //建立一个只有关闭按钮的窗口
    // SWT.MIN //建立一个不能最大化的窗口
    // SWT.MAX, //建立一个可以最大化最小化的窗口
    // SWT.NO_TRIM //建立一个没有任何边界和标题栏的窗口
    // SWT.RESIZE //建立一个可以改变大小的窗口
    // SWT.TITLE //建立一个没有标题栏图标，没有关闭按钮的窗口
    // SWT.ON_TOP //建立一个总是在上的窗口，注意：此属性最好与CLOSE、MIN、MAX一起使用。
    // SWT.TOOL //建立一个类似工具栏的窗口
    // SWT.APPLICATION_MODAL //建立一个APPLICATION模态窗口
    // SWT.MODELESS //建立一个非模态窗口
    // SWT.PRIMARY_MODAL //建立一个PRIMARY模态窗口
    // SWT.SYSTEM_MODAL //建立一个SYSTEM模态窗口
    // 还有两个快捷属性来建立窗口
    // SHELL_TRIM //建立一个标准模式的窗口，相当于属性设置为CLOSE | TITLE | MIN | MAX | RESIZE
    // DIALOG_TRIM //建立一个对话框模式的窗口，相当于属性设置为TITLE | CLOSE | BORDER
  }

  class CloseDialogAdapter implements CloseListenerAdapter {

    @Override
    public boolean close() {
      if (job != null) {
        if (job.getResult().isOK()) {
          MessageDialog.openWarning(getShell(), "关闭失败", "程序正在执行，不能关闭窗口！");
          return false;
        }
      }
      if (isDirty) {
        MessageBox messageBox = new MessageBox(getShell(), SWT.YES | SWT.NO | SWT.CANCEL);
        messageBox.setText("保存");
        messageBox.setMessage("是否保存变更的内容？");
        int status = messageBox.open();
        if (status == SWT.YES) {
          // boolean result = save();
          // if (!result) {
          // return false;
          // }
        } else if (status == SWT.CANCEL) {
          return false;
        }
      }
      return CWizardDialog.super.close();
    }
  }

  @Override
  public boolean close() {
    // boolean result = true;
    // IWizardPage currentPage = getWizard().getContainer().getCurrentPage();
    // if (currentPage instanceof BaseWizardPage) {
    // result = ((BaseWizardPage) currentPage).closePressed();
    // }
    // if (!result) {
    // return false;
    // }
    return wizardAreaComposite.closePressed();
  }

  public boolean isDirty() {
    return isDirty;
  }

  public void setDirty(boolean isDirty) {
    this.isDirty = isDirty;
  }

  public String getDialogId() {
    return dialogId;
  }

  public void setDialogId(String dialogId) {
    if (dialogId == null) {
      dialogId = BASE_DIALOG;
    } else {
      this.dialogId = dialogId;
    }
  }

  public synchronized DialogInfo getDialogInfo() {
    if (dialogInfo == null) {
      dialogInfo = DialogConfigFactory.getDialogInfo(dialogId, DialogType.WIZARD);
    }
    return dialogInfo;
  }

  public void setDialogInfo(DialogInfo dialogInfo) {
    this.dialogInfo = dialogInfo;
  }

  public Wizard getWizard() {
    return wizard;
  }

  public void setWizard(BaseWizard wizard) {
    this.wizard = wizard;
  }

}
